package com.lh.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.lh.api.config.LHConfig;
import com.lh.api.dao.*;
import com.lh.api.form.OrderForm;
import com.lh.api.service.DoboCodeService;
import com.lh.api.service.OrderService;
import com.lh.api.vo.*;
import com.lh.common.entity.admin.*;
import com.lh.common.entity.api.RazorpayOrder;
import com.lh.common.entity.state.RemarkEnum;
import com.lh.common.enums.*;
import com.lh.common.exception.RRException;
import com.lh.common.utils.*;
import com.razorpay.RazorpayClient;
import com.razorpay.RazorpayException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
	private static final Lock LOCK = new ReentrantLock();
	private static final String FIXEDCODE = "MHW";
	private static long beginIndex = 10000;
	private static final long END_INDEX = 19999;
	private static final Lock LOCKCODE= new ReentrantLock();

	@Autowired
	private UserAddressMapper userAddressMapper;

	@Autowired
	private PeriodMapper periodMapper;

	@Autowired
	private ShopMapper shopMapper;

	@Autowired
	private ActivityShopOneMapper activityShopOneMapper;

	@Autowired
	private DoboCodeMapper doboCodeMapper;

	@Autowired
	private DoboCodeService doboCodeService;

	@Autowired
	private OrderStatusLogMapper orderStatusLogMapper;

	@Autowired
	private OrderShopMapper orderShopMapper;

	@Autowired
	private ShopCartMapper shopCartMapper;

	@Autowired
	private LHConfig lhConfig;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public CreateOrderVo createOrder(Long userId, OrderForm orderForm) {
		CreateOrderVo result =new CreateOrderVo();
		String orderItem = null;
		Order order = new Order();
		orderItem = generateCode();
		order.setOrderItem(orderItem);
		order.setOrderType(orderForm.getOrderType());
		order.setOrderStatus(OrderStatusEnum.TOPAY);
		order.setUserId(userId);
		order.setShopNum(orderForm.getNum());
		order.setCreateTime(new Date());
		order.setUpdateTime(new Date());
		order.setIsDel(IsDel.NO);
		order.setPeriodId(orderForm.getPid());

		//查询用户收货地址
		QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("uaid", orderForm.getUaid()).eq("is_del","0").eq("user_id",userId);
		List<UserAddress> userAddressList = userAddressMapper.selectList(queryWrapper);
		AssertUtil.assertNotTrue(CollectionUtils.isEmpty(userAddressList), Constant.RESULT.FI1000, "Wrong user address ID, no corresponding data found");
		UserAddress address = userAddressList.get(0);
        order.setReceivePhone(address.getPhone());
        order.setReceiveRecipients(address.getRecipients());
        order.setRegion(address.getRegion());
        order.setCity(address.getCity());
        order.setDetailed(address.getDetailed());
        order.setPostalCode(address.getPostalCode());

		List<Long> sidList = null;
        //计算价格
		if(OrderTypeEnum.ONEDOLLARRUSH.equals(order.getOrderType())){//先判断是否一元购
            countAndCode(order, orderForm, userId, orderItem);
		}else{//查询普通商品
			sidList = parseShop(order,orderForm);
		}
		baseMapper.insert(order);

		//删除购物车
		if(!CollectionUtils.isEmpty(sidList)){
			delShopCart(sidList,userId);
		}

        //插入log日志
		addStatusLog(userId, order.getOid(), OrderStatusEnum.TOPAY, OrderStatusEnum.TOPAY, RemarkEnum.SHZT10);

		result.setCreateTime(order.getCreateTime());
		result.setOrderItem(orderItem);
		return result;
	}

	private void delShopCart(List<Long> sidList, Long userId) {
		if (CollectionUtils.isEmpty(sidList) || userId == null){
			return;
		}
		QueryWrapper<ShopCart> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("uid", userId).in("sid", sidList);
		shopCartMapper.delete(queryWrapper);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public RazorpayOrder payingOrder(String razorpayKeyId, String razorpayKeySecret, Long userId, String orderItem) throws RazorpayException {
		RazorpayClient razorpayClient = new RazorpayClient(razorpayKeyId, razorpayKeySecret);
		RazorpayOrder razorpayOrder  = new RazorpayOrder();

		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq(Constant.ORDER_ITEM, orderItem).eq(Constant.USER_ID,userId+"");
		Order order = baseMapper.selectOne(queryWrapper);

		//sid是商品的ID,和SHOPID不一样
		AssertUtil.assertNotNull(order, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
		AssertUtil.assertNotTrue(!order.getUserId().equals(userId), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);

		Order orderUpdate = new Order();
		AssertUtil.assertNotTrue(!OrderStatusEnum.TOPAY.equals(order.getOrderStatus()) && !OrderStatusEnum.INPAY.equals(order.getOrderStatus()),
				Constant.RESULT.FI1009, "This order's status is not pending payment,so you can not pay for it" );

		orderUpdate.setOid(order.getOid());
		orderUpdate.setOrderStatus(OrderStatusEnum.INPAY);//支付中
		orderUpdate.setUpdateTime(new Date());

		if(OrderTypeEnum.ONEDOLLARRUSH.equals(order.getOrderType())){
			//根据PID获取相关的期数
			Period period = periodMapper.selectById(order.getPeriodId());
			//判断是否过期
			AssertUtil.assertNotTrue(PeriodStatusEnum.REVEALED.equals(period.getStatus())|| IsDel.YES.equals(period.getIsDel()),
					Constant.RESULT.FI1009, Constant.ACTIVITY_EXPIRED);

		}else{
			//判断订单是否过期了
			AssertUtil.assertNotTrue(OrderStatusEnum.CANCELLED.equals(order.getOrderStatus()), Constant.RESULT.FI1009, "The order has expired and cannot be paid");
		}

		if(StringUtils.isNotEmpty(order.getPayOrderNumber()) && (OrderStatusEnum.TOPAY.equals(order.getOrderStatus())|| OrderStatusEnum.INPAY.equals(order.getOrderStatus()))){
			// 判断是否第三方支付过 支付过则返回第三方抓取的数据
			com.razorpay.Order fetchOrder = razorpayClient.Orders.fetch(order.getPayOrderNumber());
			//复制属性
			BeanUtils.copyProperties(new JSONObject(fetchOrder), razorpayOrder);
		}else{
			//生成第三方订单
			JSONObject options = new JSONObject();
			options.put("amount", MathUtil.mul(order.getShouldPrice(), new BigDecimal(100)).intValue());//支付金额 int类型
			options.put("currency", "INR");//货币类型
			options.put("payment_capture", "1");//自动捕获付款
			com.razorpay.Order payOrder = razorpayClient.Orders.create(options);
			Map<String,Object> orderPayMap = net.sf.json.JSONObject.fromObject(payOrder.toString());
			orderUpdate.setPayOrderNumber(orderPayMap.get("id").toString());//设置第三方返回的PayOrderNumber
			//复制属性
			BeanUtils.copyProperties(orderPayMap, razorpayOrder);
		}
		baseMapper.updateByKey(orderUpdate);//更新ORDER订单

		addStatusLog(userId, order.getOid(), order.getOrderStatus(), OrderStatusEnum.INPAY, RemarkEnum.SHZT11);
		return razorpayOrder;
	}

	@Override
	@Transactional
	public VerifyVo doOrderVerify(String razorpayPaymentId, boolean isTrue, String orderItem, Long userId) {
		VerifyVo result = new VerifyVo();
		boolean flag = false;
		if(isTrue ){//验证成功，判断商品库存情况等，生成夺宝码，扣减库存,记录log表
			flag = doOrderSuccess(razorpayPaymentId,orderItem, userId + "");
			if(!flag){//如果出现异常，则修改成待退款
				flag = doOrderFail(razorpayPaymentId,orderItem, userId + "");
			}
		}else{//验证不成功，订单修改成待退款,记录LOG
			flag = doOrderFail(razorpayPaymentId,orderItem, userId + "");
		}
		if(flag){
			QueryWrapper<DoboCode> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq(Constant.ORDER_ITEM, orderItem);
			List<DoboCode> doboCodes = doboCodeMapper.selectList(queryWrapper);
			if(!CollectionUtils.isEmpty(doboCodes)){
				result.setCodeList(Arrays.asList(doboCodes.get(0).getPeriodCode().split(",")));
			}
		}
		result.setResult(flag);
		return result;
	}

	/*验证成功，判断商品库存情况等，生成夺宝码，扣减库存,记录log表*/
	public boolean doOrderSuccess(String razorpayPaymentId, String orderItem, String userId) {
		boolean flag = false;
		try {
			//查询出订单详情
			QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq(Constant.ORDER_ITEM, orderItem).eq(Constant.USER_ID,userId+"");
			Order order = baseMapper.selectOne(queryWrapper);
			AssertUtil.assertNotNull(order, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
			AssertUtil.assertNotTrue(!userId.equals(order.getUserId()+""), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);

			Order orderUpdate = new Order();
			orderUpdate.setOid(order.getOid());
			orderUpdate.setOrderStatus(OrderStatusEnum.TOSHIP);
			orderUpdate.setUpdateTime(new Date());
			//支付成功信息
			orderUpdate.setPayType(PayType.PAYPAL);
			orderUpdate.setPayCallBackTime(new Date());
			orderUpdate.setPayTime(new Date());
			orderUpdate.setPayPaymentsId(razorpayPaymentId);

			//判断订单是否过期了
			AssertUtil.assertNotTrue(OrderStatusEnum.CANCELLED.equals(order.getOrderStatus()),
					Constant.RESULT.FI1009, "The order has expired and cannot be paid");

			if(!OrderStatusEnum.INPAY.equals(order.getOrderStatus())){//如果不是支付中,说明回调先触发回调，则直接返回true
				return true;
			}

			//根据PID获取相关的期数
			Period period = periodMapper.selectById(order.getPeriodId());
			if(OrderTypeEnum.ONEDOLLARRUSH.equals(order.getOrderType())){
				Period periodRecord = new Period();
				//判断是否过期
				AssertUtil.assertNotTrue(PeriodStatusEnum.REVEALED.equals(period.getStatus())|| IsDel.YES.equals(period.getIsDel()),
						Constant.RESULT.FI1009, Constant.ACTIVITY_EXPIRED);
				//生成夺宝码和扣减库存在同一把锁中  先生成夺宝码再减库存
				LOCKCODE.lock();
				//生成夺宝码
				try {
					//更新ovmal_dobo_code夺宝码
					doboCodeService.updateByOrderItem( orderItem, order.getPeriodId(), order.getShopNum());

					//扣减库存 11类型的当库存小于0则设置为0
					periodRecord.setCurrenPortion(period.getCurrenPortion() + order.getShopNum());
					if(period.getTotalPortion() <= order.getShopNum()){
						periodRecord.setTotalPortion(0);
					}else{
						periodRecord.setTotalPortion(period.getTotalPortion() - order.getShopNum());
					}

					//扣减库存
					periodRecord.setPid(period.getPid());
					periodRecord.setUpdateTime(new Date());
					periodMapper.updateByKey(periodRecord);
				} finally {
					LOCKCODE.unlock();
				}
			}

			addStatusLog(Long.parseLong(userId), order.getOid(), order.getOrderStatus(), OrderStatusEnum.TOSHIP, RemarkEnum.SHZT12);

			baseMapper.updateByKey(orderUpdate);//更新ORDER订单
			flag = true;
		} catch (Exception e) {
			flag = false;
			log.error("doOrderSuccess 异常："+e);
		}
        return flag;
	}

	/*验证不成功，订单修改成待退款,记录LOG*/
	public boolean doOrderFail(String razorpayPaymentId,String orderItem, String userId) {
		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq(Constant.ORDER_ITEM, orderItem).eq(Constant.USER_ID,userId);
		Order order = baseMapper.selectOne(queryWrapper);

		//订单中如果有第三方支付ID说明支付过了，不需要处理了
		if(StringUtils.isNotEmpty(order.getPayPaymentsId())){
			return false;
		}

		Order orderUpdate = new Order();
		orderUpdate.setOid(order.getOid());
		orderUpdate.setUpdateTime(new Date());
		//支付相关信息
		orderUpdate.setPayType(PayType.PAYPAL);
		orderUpdate.setPayCallBackTime(new Date());
		orderUpdate.setPayPaymentsId(razorpayPaymentId);
		orderUpdate.setPayTime(new Date());

		//记录订单修改状态
		if(OrderTypeEnum.ONEDOLLARRUSH.equals(order.getOrderType())){
			addStatusLog(Long.parseLong(userId), order.getOid(), order.getOrderStatus(), OrderStatusEnum.CANCELLED, RemarkEnum.SHZT17);
		}else {
			addStatusLog(Long.parseLong(userId), order.getOid(), order.getOrderStatus(), OrderStatusEnum.ACTIVITYLOSE, RemarkEnum.SHZT17);
		}

		baseMapper.updateByKey(orderUpdate);//更新ORDER订单
		return false;
	}

	private void addStatusLog(Long userId, Long oid, OrderStatusEnum oldStatus, OrderStatusEnum newStatus, String remark) {
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setUserId(userId);
        orderStatusLog.setOrderId(oid);
        orderStatusLog.setOldStatus(oldStatus);
        orderStatusLog.setNewStatus(newStatus);
        orderStatusLog.setCreateTime(new Date());
        orderStatusLog.setUpdateTime(new Date());
        orderStatusLog.setRemark(remark);
        orderStatusLogMapper.insert(orderStatusLog);
    }

    /**
    　* @description: 计算商品价格运费并添加夺宝码
    　* @author GaoZien
    　* @date 2020/5/19 0019
    */
    private void countAndCode(Order order, OrderForm orderForm, Long userId, String orderItem) {
        Period periodCurrent = periodMapper.selectById(orderForm.getPid());//传入的这一期
        if(periodCurrent == null || PeriodStatusEnum.REVEALED.equals(periodCurrent.getStatus())
                || IsDel.YES.equals(periodCurrent.getIsDel())){
            throw new RRException( Constant.RESULT.FI1000, "Activity has been removed");
        }

        //查询一元购的商品详情
        ActivityShopOne activityShopOne = activityShopOneMapper.selectById(periodCurrent.getAid());

        //判断订单期数是否为过期
        AssertUtil.assertNotTrue(PeriodStatusEnum.REVEALED.equals(periodCurrent.getStatus())|| IsDel.YES.equals(periodCurrent.getIsDel()),
                Constant.RESULT.FI1000, Constant.ACTIVITY_EXPIRED);

        //订单数量和价格
        order.setFreight(new BigDecimal(0));
        order.setShouldPrice(MathUtil.mul(activityShopOne.getShopActivityPrice(),new BigDecimal( orderForm.getNum())));
        order.setPayPrice(order.getShouldPrice());
		order.setAid(activityShopOne.getAid());
		//判断是否筹集满
		AssertUtil.assertNotTrue(periodCurrent.getTotalPortion() == 0, Constant.RESULT.FI1000,"Purchasing completed");
		//判断是否有库存即剩余人次>=购买数量
		AssertUtil.assertNotTrue(periodCurrent.getTotalPortion() < orderForm.getNum(), Constant.RESULT.FI1000,"Insufficient inventory");
//        AssertUtil.assertNotTrue(order.getFreight().compareTo(orderForm.getFreight())!= 0, Constant.RESULT.FI1000,"Wrong shipping fee, actual fee:" + order.getFreight());
        AssertUtil.assertNotTrue(order.getShouldPrice().compareTo(orderForm.getShouldPrice())!= 0, Constant.RESULT.FI1000,"Wrong total price of item,actual price：" + order.getShouldPrice());
        AssertUtil.assertNotTrue(order.getPayPrice().compareTo(orderForm.getPayPrice())!= 0, Constant.RESULT.FI1000,"Wrong actual payment, actual payment should be:" + order.getPayPrice());

        //插入一条数据到ovmal_dobo_code
        DoboCode doboCode = new DoboCode();
        doboCode.setPeriodId(orderForm.getPid());
        doboCode.setUserId(userId);
        doboCode.setOrderItem(orderItem);
        doboCode.setBuyTime(new Date());
        doboCode.setCreateTime(new Date());
        doboCode.setUpdateTime(new Date());
        doboCode.setIsDel(IsDel.NO);
        doboCodeMapper.insert(doboCode);
    }

    private List<Long> parseShop(Order order, OrderForm orderForm) {
		List<String> shopNumIdList = Arrays.asList(orderForm.getShopNums().split(","));
		List<OrderShop> orderShops = new ArrayList<>();
		List<Long> sidList = new ArrayList<>();
		OrderShop temp = null;
		BigDecimal freight = new BigDecimal(0);
		BigDecimal payPrice = new BigDecimal(0);
		BigDecimal shouldPrice = new BigDecimal(0);
		int sort =0;
		for(String shopNumId : shopNumIdList){
			String[] shopArr = shopNumId.split("_");
			if(shopArr.length != 2 ){
				continue;
			}
			Shop shop = shopMapper.selectById(shopArr[0]);
			if(shop == null||UpperLowerShelfStatus.LOWERSHELF.equals(shop.getStatus()) || IsDel.YES.equals(shop.getIsDel())){
                throw new RRException(Constant.RESULT.FI1000, "This goods has been removed");
            }
			BigDecimal freightSimple  = BigDecimal.valueOf(0);
			if(IF.NO.equals(shop.getIsFreight())){
				freightSimple =  getFreight(shop.getFirstFreight(), shop.getNoFirstFreight(), Integer.parseInt(shopArr[1]));
				freight = MathUtil.add(freight, freightSimple);
			}

			BigDecimal shouldPriceSimple = MathUtil.mul(shop.getPrice(), new BigDecimal(shopArr[1]));
			shouldPrice = MathUtil.add(shouldPrice, shouldPriceSimple);

			payPrice = MathUtil.add(freightSimple, shouldPriceSimple).add(payPrice);//应付款=运费+商品总价
			//生成OrderShop
			temp = new OrderShop();
			BeanUtils.copyProperties(shop, temp);
			temp.setNum(Integer.parseInt(shopArr[1]));
			temp.setSid(Long.parseLong(shopArr[0]));
			temp.setOrderItem(order.getOrderItem());
			temp.setPayPrice(MathUtil.add(freightSimple, shouldPriceSimple));
			temp.setShopName(shop.getName());
			temp.setShopImg(shop.getMainimg());
			temp.setCreateTime(new Date());
			temp.setFreight(freightSimple);
			temp.setUpdateTime(new Date());
			temp.setSort(sort);
			temp.setSum(shouldPriceSimple);
			orderShops.add(temp);
			sort++;
			sidList.add(temp.getSid());

		}
		order.setFreight(freight);//计算运费
		order.setPayPrice(payPrice);
		order.setShouldPrice(shouldPrice);
		if(!orderShops.isEmpty()){
			orderShopMapper.insertList(orderShops);
		}
        AssertUtil.assertNotTrue(order.getFreight().compareTo(orderForm.getFreight()) != 0, Constant.RESULT.FI1009,"Wrong shipping fee, actual fee: " + order.getFreight());
        AssertUtil.assertNotTrue(order.getShouldPrice().compareTo(orderForm.getShouldPrice()) != 0, Constant.RESULT.FI1009,"Wrong total price of item,actual price：" + order.getShouldPrice());
        AssertUtil.assertNotTrue(order.getPayPrice().compareTo(orderForm.getPayPrice()) != 0, Constant.RESULT.FI1009,"Wrong actual payment, actual payment should be:" + order.getPayPrice());
        return sidList;
    }

	//计算运费
	public BigDecimal getFreight(BigDecimal firstFreight, BigDecimal noFirstFreight, int num) {
		BigDecimal price = null;
		if(firstFreight == null){
			firstFreight = BigDecimal.valueOf(0.0);
		}
		if(noFirstFreight == null){
			noFirstFreight = BigDecimal.valueOf(0.0);
		}
		if(num == 1){
			price = firstFreight;
		}else {
			price =  firstFreight.add( BigDecimal.valueOf((num-1)).multiply(noFirstFreight) );
		}
		return price;
	}



	//生成订单号
	public static String generateCode(){
		LOCK.lock();
		String code = "";
		try {
			SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMddHHmmssSSS");
			Date current = new Date();
			String date = sdf.format(current);
			if(beginIndex >= END_INDEX ){
                beginIndex = 10001;
			}else {
                beginIndex = beginIndex + 1;
			}
			String str = String.valueOf(beginIndex);
			code = FIXEDCODE + (date +str.substring(1, str.length()));
		} catch (NumberFormatException e) {
			log.error("NumberFormatException:{}", e);
		} finally {
			LOCK.unlock();
		}
		return code;
	}

	@Transactional
	@Override
	public boolean orderPayCallback(String jsonStr) {
		boolean flag = false;
		JSONObject jsonObject = new JSONObject(jsonStr);
		String event = jsonObject.get("event").toString();
		if(EventType.payment_captured.getValue().equals(event)){
           /* 如果支付成功，则先判断这个订单在自己平台上是否成功支付了，
           如果状态是支付成功（验证成功）或者待退款（验证失败或者验证异常）则直接不操作，
           如果是其他状态则修改成要退款*/
			JSONObject payload = (JSONObject)jsonObject.get("payload");
			JSONObject payment = (JSONObject)payload.get("payment");
			JSONObject entity = (JSONObject)payment.get("entity");
			String orderId = entity.get("order_id").toString();//获取回调的第三方订单ID
			String payId = entity.get("id").toString();//获取回调的第三方支付ID

			QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("pay_order_number",orderId);
			List<Order> orders = baseMapper.selectList(queryWrapper);
			if(orders == null){
				log.error("orderPayCallback:"+orderId+"第三方订单号不存在。"+jsonObject.toString());
				return false;
			}
			Order order = orders.get(0);
			if(OrderStatusEnum.INPAY.equals(order.getOrderStatus())){// 如果是支付中说明没有执行到订单验证方法，此时直接生成夺宝码
				flag = doOrderSuccess(payId,order.getOrderItem(),order.getUserId()+"");
				if(!flag){//如果出现异常，则修改成待退款
					doOrderFail(payId,order.getOrderItem(),order.getUserId()+"");
				}
			}else  if(OrderStatusEnum.COMPLETED.equals(order.getOrderStatus()) ){//如果是定时任务刷新导致一元购订单状态为已过期，则修改成待退款
				doOrderFail(payId,order.getOrderItem(),order.getUserId()+"");
			}
		}
		return true;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(String orderItem, Long userId) {
		Order oldOrder = baseMapper.selectByItem(orderItem);
		AssertUtil.assertNotNull(oldOrder, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
		AssertUtil.assertNotTrue(!userId.equals(oldOrder.getUserId()), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);

		//修改订单状态
		Order order = new Order();
		order.setOid(oldOrder.getOid());
		order.setUpdateTime(new Date());
		order.setOrderStatus(OrderStatusEnum.CANCELLED);
		//记录订单修改状态
		addStatusLog(oldOrder.getUserId(), oldOrder.getOid(), oldOrder.getOrderStatus(), OrderStatusEnum.CANCELLED, RemarkEnum.SHZT16);
		baseMapper.updateByKey(order);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelPayment(String orderItem, Long userId) {
		Order oldOrder = baseMapper.selectByItem(orderItem);
		AssertUtil.assertNotNull(oldOrder, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
		AssertUtil.assertNotTrue(!userId.equals(oldOrder.getUserId()), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);

		//修改订单状态
		Order order = new Order();
		order.setOid(oldOrder.getOid());
		order.setUpdateTime(new Date());
		order.setOrderStatus(OrderStatusEnum.TOPAY);
		baseMapper.updateByKey(order);

		//记录订单修改状态
		addStatusLog(userId, oldOrder.getOid(), oldOrder.getOrderStatus(), OrderStatusEnum.TOPAY, RemarkEnum.SHZT26);
	}

    @Override
    public PageUtils<OneOrderListVo> getOneOrderList(Map<String, Object> params, Integer pageNum, Integer pageSize) {
        if(pageNum != null && pageSize != null){
            PageHelper.startPage(pageNum, pageSize);
        }
        List<OneOrderListVo> oneOrderList = this.baseMapper.getOneOrderList(params);
        for (OneOrderListVo oneOrderListVo : oneOrderList){
            if(OrderStatusEnum.PAYCANCEL.equals(oneOrderListVo.getOrderStatus()) || OrderStatusEnum.PAYOVERTIME.equals(oneOrderListVo.getOrderStatus()) || OrderStatusEnum.ACTIVITYLOSE.equals(oneOrderListVo.getOrderStatus())){
                oneOrderListVo.setOrderStatus(OrderStatusEnum.CANCELLED);
            }
        }

        return new PageUtils<>(oneOrderList);
    }

	@Override
	public OneOrderDetailVo getOneOrderDetail(Long userId, String orderItem) {
		OneOrderDetailVo result = this.baseMapper.getOneOrderDetail(userId, orderItem);
		if(result == null){
			return new OneOrderDetailVo();
		}
		if(StringUtils.isNotEmpty(result.getProperty())){
			result.setPropertyList(ShopServiceImpl.parseData(result.getProperty()));
		}
		if(StringUtils.isNotEmpty(result.getPeriodCode())){
			result.setCodeList(Arrays.asList(result.getPeriodCode().split(",")));
		}
		result.setCustomrPhone(lhConfig.getCustomerPhone());
		//检查是否支付超时
		if(OrderStatusEnum.TOPAY.equals(result.getOrderStatus()) || OrderStatusEnum.INPAY.equals(result.getOrderStatus())){
			Long remainingTime = (long) DateTimeUtil.getRemainingTime(new Date(result.getCreateTime().getTime()+1000*60*5));
			result.setRemainingTime(OrderStatusEnum.TOPAY.equals(result.getOrderStatus()) ? remainingTime : 0);
			if(remainingTime == 0l){
				//修改订单状态
				Order order = new Order();
				order.setOid(result.getOid());
				order.setUpdateTime(new Date());
				order.setOrderStatus(OrderStatusEnum.PAYOVERTIME);
				//记录订单修改状态
				addStatusLog(userId, result.getOid(), result.getOrderStatus(), order.getOrderStatus(), RemarkEnum.SHZT22);
				baseMapper.updateByKey(order);
				result.setOrderStatus(order.getOrderStatus());
			}
		}
		if(OrderStatusEnum.PAYOVERTIME.equals(result.getOrderStatus()) ){
			result.setCancelType(CancelTypeEnum.PAYOVERTIME);
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		if(OrderStatusEnum.PAYCANCEL.equals(result.getOrderStatus()) ){
			result.setCancelType(CancelTypeEnum.PAYCANCEL);
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		if(OrderStatusEnum.ACTIVITYLOSE.equals(result.getOrderStatus()) ){
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		return result;
	}

	@Override
	public PageUtils<OrderListVo> getOrderList(Map<String, Object> params, Integer pageNum, Integer pageSize) {
		if(pageNum != null && pageSize != null){
			PageHelper.startPage(pageNum, pageSize);
		}
		List<OrderListVo> orderListVos = this.baseMapper.getOrderList(params);

		for (OrderListVo orderListVo : orderListVos){
			if(StringUtils.isNotEmpty(orderListVo.getProperty())){
				orderListVo.setPropertyList(ShopServiceImpl.parseData(orderListVo.getProperty()));
			}
			//整合状态
			if(OrderStatusEnum.PAYCANCEL.equals(orderListVo.getOrderStatus()) || OrderStatusEnum.PAYOVERTIME.equals(orderListVo.getOrderStatus()) || OrderStatusEnum.ACTIVITYLOSE.equals(orderListVo.getOrderStatus())){
				orderListVo.setOrderStatus(OrderStatusEnum.CANCELLED);
			}
			if(OrderStatusEnum.OUTSTOCK.equals(orderListVo.getOrderStatus()) ){
				orderListVo.setOrderStatus(OrderStatusEnum.SHIPED);
			}
		}
		return new PageUtils<>(orderListVos);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public OrderDetailVo getOrderDetail(Long userId, String orderItem) {
		OrderDetailVo result = this.baseMapper.getOrderDetail(userId, orderItem);
		for (OrderShopVo orderShopVo : result.getShopList()){
			if(StringUtils.isNotEmpty(orderShopVo.getProperty())){
				orderShopVo.setPropertyList(ShopServiceImpl.parseData(orderShopVo.getProperty()));
			}
		}
		result.setCustomrPhone(lhConfig.getCustomerPhone());
		if(OrderStatusEnum.TOPAY.equals(result.getOrderStatus()) || OrderStatusEnum.INPAY.equals(result.getOrderStatus())){
			result.setRemainingTime((long) DateTimeUtil.getRemainingTime(new Date(result.getCreateTime().getTime()+1000*60*15)));
			if(result.getRemainingTime() == 0l){
				//修改订单状态
				Order order = new Order();
				order.setOid(result.getOid());
				order.setUpdateTime(new Date());
				order.setOrderStatus(OrderStatusEnum.PAYOVERTIME);
                result.setOrderStatus(OrderStatusEnum.PAYOVERTIME);
				//记录订单修改状态
				addStatusLog(userId, result.getOid(), result.getOrderStatus(), OrderStatusEnum.PAYOVERTIME, RemarkEnum.SHZT22);
				baseMapper.updateByKey(order);
			}
		}

		if(OrderStatusEnum.PAYOVERTIME.equals(result.getOrderStatus()) ){
			result.setCancelType(CancelTypeEnum.PAYOVERTIME);
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		if(OrderStatusEnum.PAYCANCEL.equals(result.getOrderStatus()) ){
			result.setCancelType(CancelTypeEnum.PAYCANCEL);
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		if(OrderStatusEnum.ACTIVITYLOSE.equals(result.getOrderStatus()) ){
			result.setOrderStatus(OrderStatusEnum.CANCELLED);
		}
		if(OrderStatusEnum.OUTSTOCK.equals(result.getOrderStatus()) ){
			result.setOrderStatus(OrderStatusEnum.SHIPED);
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void confirmOrder(String orderItem, Long userId) {
		Order oldOrder = baseMapper.selectByItem(orderItem);

		AssertUtil.assertNotTrue(oldOrder == null, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
		AssertUtil.assertNotTrue(!userId.equals(oldOrder.getUserId()), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);
		//记录订单修改状态
		addStatusLog(userId, oldOrder.getOid(), oldOrder.getOrderStatus(), OrderStatusEnum.COMPLETED, RemarkEnum.SHZT15);

		Order order = new Order();
		order.setOid(oldOrder.getOid());
		order.setOrderStatus(OrderStatusEnum.COMPLETED);
		order.setSignTime(new Date());
		baseMapper.updateByKey(order);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delOrder(String orderItem, Long userId) {
		Order oldOrder = baseMapper.selectByItem(orderItem);
		AssertUtil.assertNotTrue(oldOrder == null, Constant.RESULT.FI1000, Constant.ORDER_NOT_EXIST);
		AssertUtil.assertNotTrue(!userId.equals(oldOrder.getUserId()), Constant.RESULT.FI1000, Constant.USER_NOT_MATCH);
		//一元夺宝订单不能删除
		if(OrderTypeEnum.ONEDOLLARRUSH.equals(oldOrder.getOrderType())){
			return;
		}
		AssertUtil.assertNotTrue(!OrderStatusEnum.CANCELLED.equals(oldOrder.getOrderStatus())
                        && !OrderStatusEnum.PAYOVERTIME.equals(oldOrder.getOrderStatus())
                        && !OrderStatusEnum.PAYCANCEL.equals(oldOrder.getOrderStatus()),
				Constant.RESULT.FI1009, "Only cancelled orders can be deleted");

		//记录订单修改状态
		Order order = new Order();
		order.setOid(oldOrder.getOid());
		order.setIsDel(IsDel.YES);
		baseMapper.updateByKey(order);
	}

	@Override
	public Order selectByItem(String orderItem) {
		return baseMapper.selectByItem(orderItem);
	}

	@Override
	public void updateBykey(Order order) {
		baseMapper.updateByKey(order);
	}
}
